O naufrágio do Titanic é um dos eventos mais conhecidos da história marítima. Em 15 de abril de 1912, o navio que era considerado inafundável colidiu com um iceberg e afundou, resultando na morte de mais de 1.500 pessoas. Esse trágico acontecimento gerou grande comoção na época e, desde então, tem sido objeto de inúmeras investigações e estudos.

Introdução

Com base nos dados do Titanic, apresentaremos a seguir uma análise sobre os passageiros do navio que naufragou em 1912. Serão explorados diversos aspectos, como a distribuição das classes sociais, a relação entre gênero e sobrevivência, a idade dos passageiros, entre outros fatores relevantes.

Objetivo

O objetivo da análise é investigar e compreender o perfil dos passageiros e explorar as características que podem ter influenciado as chances de sobrevivência dos passageiros. A fonte dos dados utilizados pode variar, mas algumas das mais comuns são os registros oficiais dos passageiros do Titanic disponíveis publicamente, como os fornecidos pelo site Kaggle https://www.kaggle.com/c/titanic/data e pelo Museu Marítimo Nacional dos EUA https://www.maritime.org/titanic/passengers.htm.

Bibliotecas

# Coleção de pacotes para manipulação e visualização de dados
if(!require(tidyverse)) install.packages('tidyverse');library(tidyverse)

# Crição de gráficos e visualizações estatísticas
if(!require(ggplot2)) install.packages('ggplot2');library(ggplot2)

# Manipulação de dados, como filtragem, seleção e agregação
if(!require(dplyr)) install.packages('dplyr');library(dplyr)

# Plotar matrizes de correlação usando ggplot2
if(!require(ggcorrplot)) install.packages('ggcorrplot');library(ggcorrplot)
if(!require(plotly)) install.packages('plotly');library(plotly)

# Funções para ajustar a escala dos eixos em gráficos ggplot2
if(!require(scales)) install.packages('scales');library(scales)

# Fornece funções para manipulação de strings
if(!require(stringr)) install.packages('stringr');library(stringr)

Importação dos Dados

df <- read.csv('data/titanic.csv') # Variável principal `Survived
head(df, 3)
Variável Descrição
PassengerId Número de identificação do passageiro
Survived Passageiro sobreviveu ao naufrágio? (0 = Não; 1 = Sim)
Pclass Classe onde o passageiro estava no navio (1 = 1ª classe; 2 = 2ª classe; 3 = 3ª classe)
Name Nome do passageiro
Sex Sexo biológico
Age Idade
SibSp Número de irmãos ou cônjuges a bordo
Parch Número de pais ou filhos a bordo
Ticket Número do ticket de embarque (passagem)
Fare Valor da tarifa (preço da passagem) em Libras Esterlinas
Cabin Identificação da cabine
Embarked Porto de embarque (C = Cherbourg; Q = Queenstown; S = Southampton)

Análise da Populacional

Vizualização pelo Sexo
# Contar número de passageiros por sexo
passengers_by_sex <- df %>%
  group_by(Sex) %>%
  summarise(count = n())

# Calcular proporção
passengers_by_sex$prop <- passengers_by_sex$count / sum(passengers_by_sex$count)

# Criar gráfico de barras empilhadas
ggplot(passengers_by_sex, aes(x = Sex, y = prop, fill = Sex)) +
  geom_bar(stat = "identity", position = "stack") +
  geom_text(aes(label = paste(count, "(", scales::percent(prop), ")")), 
            position = position_stack(vjust = 0.5), size=4) +
  labs(title = "Distribuição de passageiros por sexo", x = "Sexo", y = "Proporção") +
  scale_fill_manual(values = c("#998ec3", "#6da8f6")) +
  theme(axis.text.x = element_text(angle = 0, vjust = 0.5, hjust=1))

Vizualização pela Sobrevivencia
df %>%
  group_by(Survived) %>%
  summarise(count = n()) %>%
  mutate(prop = count / sum(count), 
         percent = paste0(round(prop * 100, 1), "%")) %>%
  ggplot(aes(x = factor(Survived), y = count, fill = factor(Survived))) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = percent), 
            position = position_stack(vjust = 0.5)) +
  labs(title = "Quantidade de sobreviventes e mortos",
       x = "Sobreviveu?",
       y = "Quantidade") +
  scale_fill_manual(name = "Sobreviveu?",
                    values = c("#d3290f", "#52d053"),
                    labels = c("Não", "Sim"))

Correlações e Direções

# Seleciona apenas as variáveis numéricas e remove linhas com valores faltantes
# Criar o gráfico de correlação
df %>%
  select_if(is.numeric) %>%  # seleciona apenas as variáveis numéricas
  na.omit() %>%  # remove as linhas com valores faltantes
  cor() %>%  # calcula a correlação entre as variáveis
  ggcorrplot(lab = TRUE, lab_size = 3, hc.order = TRUE, type = "lower")  # cria o gráfico

Análise dos Componentes Principais

# Criar uma variável binária para o gênero e remover as linhas com valores faltantes
df_pca <- df %>% 
  mutate(Genere = ifelse(Sex == 'female', 1, 0 )) %>%  # cria uma variável binária para o gênero
  select(Survived, Pclass, Genere, Age, SibSp, Parch, Fare) %>%  # seleciona as variáveis numéricas relevantes
  drop_na()  # remove as linhas com valores faltantes

# Normaliza os dados e executa o PCA
df_pca_norm <- apply(df_pca, 2, scale) # normaliza os dados excluindo a primeira coluna (Survived)
pca <- prcomp(df_pca_norm)  # realiza o PCA

# Exibe informações sobre as componentes principais
summary(pca)
Importance of components:
                          PC1    PC2    PC3    PC4     PC5     PC6     PC7
Standard deviation     1.4573 1.3179 1.0561 0.8467 0.75108 0.65490 0.56059
Proportion of Variance 0.3034 0.2481 0.1593 0.1024 0.08059 0.06127 0.04489
Cumulative Proportion  0.3034 0.5515 0.7108 0.8133 0.89384 0.95511 1.00000

Visualização dos 3PCA | 71% dos Dados

A visualização gráfica das 3 primeiras componentes principais mostrou que houve uma separação entre os passageiros que sobreviveram e os que não sobreviveram, sugerindo que essas variáveis foram importantes

# Cria o dataframe com as três primeiras componentes principais e adiciona a variável 'Survived'
df_pca_plot_3d <- as.data.frame(pca$x[, 1:3])  # extrai as três primeiras componentes principais
df_pca_plot_3d$Survived <- factor(df_pca$Survived, levels = c(0, 1), labels = c("Morreu", "Viveu"))  #
df_pca_plot_3d$Pclass <- factor(df_pca$Pclass, levels = c(1, 2, 3), labels = c("3", "2", "1"))
df_pca_plot_3d$Genere <- factor(df_pca$Genere, levels = c(0, 1), labels = c("Homem", "Mulher"))
df_pca_plot_3d$SibSp <- factor(df_pca$SibSp, levels = c(0, 1, 2, 3, 4, 5, 6), labels = c("0", "1", "2", "3", "4", "5", "6"))

# Cria o gráfico de dispersão das componentes principais em 3D
plot_ly(df_pca_plot_3d, x = ~PC1, y = ~PC2, z = ~PC3, color = ~factor(Survived), type = "scatter3d", mode = "markers",
        colors = c("#EE2E21", "#1D7874"), marker = list(size = 5)) %>%
  layout(scene = list(xaxis = list(title = "Componente Principal 1"),
                      yaxis = list(title = "Componente Principal 2"),
                      zaxis = list(title = "Componente Principal 3")),
         legend = list(title = "Sobreviveu"), title = "Análise de Componentes Principais em 3D")

Componentes pelo Genero

plot_ly(df_pca_plot_3d, x = ~PC1, y = ~PC2, z = ~PC3, color = ~factor(Genere), type = "scatter3d", mode = "markers",
        colors = c("#3784B9", "#B9375E"), marker = list(size = 5)) %>%
  layout(scene = list(xaxis = list(title = "Componente Principal 1"),
                      yaxis = list(title = "Componente Principal 2"),
                      zaxis = list(title = "Componente Principal 3")),
         legend = list(title = "Sexo"), title = "Análise de Componentes Principais pelo Gênero")

Componentes pela Classe

plot_ly(df_pca_plot_3d, x = ~PC1, y = ~PC2, z = ~PC3, color = ~factor(Pclass), type = "scatter3d", mode = "markers",
        colors = c("#cf2da4", "#2dcf3e", "#2d48cf"), marker = list(size = 5)) %>%
  layout(scene = list(xaxis = list(title = "Componente Principal 1"),
                      yaxis = list(title = "Componente Principal 2"),
                      zaxis = list(title = "Componente Principal 3")),
         legend = list(title = "Sobreviveu"), title = "Análise de Componentes Principais em 3D")

Direção das Variáveis

Utilidade: Entender como as variáveis se relacionam entre si e com as componentes principais, permitindo a identificação de padrões e tendências

biplot(pca, scale = 0, cex = 0.6, col = c("white", "#0046FF"))

Sobrevivência por Gênero

Agrupar os dados por gênero e sobrevivência e calcular as porcentagens de sobrevivência por gênero

  • Mesmo com o maior número de homens na embarcação. O número de sobreviventes do sexo feminino foi maior que do sexo masculino.

  • O número de mulheres sobreviventes foi cerca de 3x maior que o número de homens sobreviventes.

# agrupar dados e calcular porcentagens
survival_by_gender <- df %>%
  group_by(Sex, Survived) %>%
  summarise(count = n()) %>%
  mutate(percent = count / sum(count) * 100)
`summarise()` has grouped output by 'Sex'. You can override using the `.groups` argument.
# plotar gráfico
ggplot(survival_by_gender, aes(x = Sex, y = percent, fill = factor(Survived))) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("#d15252", "#52d053"), labels = c("Não Sobreviveu", "Sobreviveu")) +
  labs(x = "Gênero", y = "Porcentagem", fill = "") +
  theme(plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
        axis.title.x = element_text(size = 14),
        axis.title.y = element_text(size = 14),
        axis.text = element_text(size = 12),
        legend.position = "bottom",
        legend.title = element_blank(),
        legend.text = element_text(size = 12),
        panel.grid.major.y = element_line(color = "gray90", size = 0.5),
        panel.grid.minor = element_blank()) +
  guides(fill = guide_legend(reverse = TRUE, override.aes = list(size=5))) +
  geom_text(aes(label = paste0(count, " (", sprintf("%.1f", percent), "%)"), y = percent), 
            position = position_stack(vjust = 0.5), size = 4, color = "#202124")

Distribuição de Idade dos Passageiros do Titanic

Agrupar os passageiros por faixa etária e analisar o número de pessoas por faixa no barco

  • Distribuição de idade em uma escala de 0 a 80 anos. Ajuda a entender melhor como as idades estão distribuídas entre os passageiros do navio

  • A número de passageiros entre 20 e 50 anos é dominante comparado as demais idades. A média de idade está por volta de 30 anos.

ggplot(df, aes(x = Age)) +
  geom_histogram(bins = 20, binwidth = 2, fill = "#5328d4", color = "#202124") +
  labs(title = "Distribuição de Idade dos Passageiros", x = "Idade", y = "Frequência") +
  theme(plot.title = element_text(size = 14, hjust = 0.5),
        axis.title.x = element_text(size = 14),
        axis.title.y = element_text(size = 14),
        axis.text = element_text(size = 12),
        legend.position = "bottom") +
  scale_x_continuous(breaks = seq(0, 80, 10)) +
  geom_vline(aes(xintercept = mean(Age, na.rm = TRUE)), color = "#86d94e", linetype = "dashed", size = 1) +
  annotate("text", x = mean(df$Age, na.rm = TRUE), y = max(df$Age) * 0.9, label = "Média da Idade", color = "#202124", size = 5, fontface = "bold") +
  guides(fill = guide_legend(title = "Legenda"))
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.

Densidade

Agrupar as pessoas por idade e analiasar a densidade da sobrevivência.

  • Número relativo de jovens que sobreviveram foi maior que as demais faixas etárias.

  • Mesmo assim, o número de jovens mortos chega a cerca de 50% do valor total de jovens na embarcação.

  • Número de mortos por volta de 23 anos é muito maior que o número de sobreviventes.

  • chance de sobrevivência cai ao passo que a idade do passageiro aumenta.

# Remover observações com idade faltante
df_age <- df[!is.na(df$Age),]

# Gráfico de densidade para cada grupo de sobreviventes
ggplot(df_age, aes(x = Age, fill = factor(Survived))) +
  geom_density(alpha = 0.5) +
  labs(title = "Densidade da idade dos passageiros por sobrevivência",
       x = "Idade",
       y = "Densidade") + theme(legend.position = "bottom") +
  scale_fill_manual(name = "Sobreviveu?",
                    values = c("#d3290f", "#52d053"),
                    labels = c("Não", "Sim"))

Relacionamento entre Sobrevivência e Idade por Sexo

Identificar se há alguma relação entre a idade dos passageiros do Titanic e suas chances de sobrevivência, levando em consideração o sexo dos passageiros -

  • Novamente, observamos o maior número relativo de mortes dentre homens e, principalmente, de 20 a 50 anos.

  • Há um caso que aumenta a chance de sobreviência acima de 80 anos dentre homens.

df %>%
  na.omit() %>%
  mutate(age_group = cut(Age, breaks = seq(0, max(Age) + 5, by = 5), right = FALSE, labels = paste0(seq(0, max(Age), by = 5), "-", seq(4, max(Age), by = 5)))) %>%
  count(age_group, Survived, Sex) %>%
  mutate(Percentage = round(n/sum(n)*100,2)) %>%
  ggplot(aes(x = age_group, y = n, fill = factor(Survived))) +
  geom_col(position = "dodge") +
  geom_text(aes(label = paste0(Percentage, "%")), position = position_dodge(width = 1), vjust = -0.5, color = "#202124", size = 3) +
  scale_fill_manual(name = "Sobreviveu?", values = c("#d3290f", "#52d053"), labels = c("Não", "Sim")) +
  facet_wrap(~ Sex) +
  labs(title = "Frequência de Sobreviventes e Mortes por Idade e Sexo", x = "Idade", y = "Frequência") +
  theme(legend.position = "bottom")

Taxa de Sobrevivencia

Relação do número de mortes pelo número total de passageiros por faixa etária.

  • Aumento da proporção de mortes por faixa etária. Entretanto, como já observado, faixa de 19 até 30 anos permanece a com maior densidade de mortes.

  • 50% dos jovens com 0 a 18 anos não sobreviveu

# Criando um data frame com as variáveis de interesse
df_age_fare <- df %>%
  select(Age, Fare, Survived) %>%
  na.omit()

# Criando variáveis para categorizar as idades
df_age_fare$age_group <- cut(df_age_fare$Age, 
                             breaks = c(0, 18, 30, 50, Inf), 
                             labels = c("0-18", "19-30", "31-50", "51+"))

# Criando uma nova variável para armazenar as informações sobre sobrevivência
df_age_fare$survival <- ifelse(df_age_fare$Survived == 1, "Survived", "Died")

# Calculando a proporção de sobreviventes e mortos em cada faixa etária
df_age_fare_summary <- df_age_fare %>%
  group_by(age_group, survival) %>%
  summarise(count = n()) %>%
  mutate(prop = count / sum(count))
`summarise()` has grouped output by 'age_group'. You can override using the `.groups` argument.
# Criando um gráfico de barras empilhadas para visualizar a proporção de sobreviventes e mortos em cada faixa etária
ggplot(df_age_fare_summary, aes(x = age_group, y = prop, fill = survival)) +
  geom_bar(stat = "identity") +
  labs(title = "Proporção de sobreviventes e mortos por faixa etária",
       x = "Faixa etária",
       y = "Proporção") +
  scale_fill_manual(name = "Sobrevivência", 
                    values = c("Died" = "#d3290f", "Survived" = "#52d053"),
                    labels = c("Mortos", "Sobreviventes"))

Probabilidade de Sobrevivencia pela Classe

Relação do número de mortes pelo número total de passageiros por classe de passageiros.

df %>%
  group_by(Pclass, Survived) %>%
  summarise(count = n(), .groups = "drop") %>%
  mutate(Percentage = round(count/sum(count)*100,2)) %>%
  mutate(Survived = ifelse(Survived == 1, "Survived", "Died")) %>%
  ggplot(aes(x = factor(Pclass), y = Percentage, fill = Survived)) +
  geom_col(position = "dodge") +
  geom_text(aes(label = paste0(count)), position = position_dodge(width = 1), vjust = -0.5, color = "#202124", size = 3) +
  geom_text(aes(label = paste0(round(Percentage, 0), "%")), position = position_dodge(width = 1), vjust = 1.5, color = "black", size = 3) +
  scale_fill_manual(name = "Situação", values = c("#d3290f", "#52d053"), labels = c("Vasco", "Viveu")) +
  scale_x_discrete(limits=c("1", "2", "3")) +
  labs(title = "Quantidade de sobreviventes e óbitos por classe de passageiros", x = "Classe", y = "Proporção")

Análise nas Mesmas Proporções

Número bruto de sobreviventes e não sobreviventes por classe e sexo.

  • Novamente, percebe-se a maior porcentagem de sobrevivência entre mulheres, principalmente de classes mais altas.

  • Interessante o fato de que o número de mulheres que sobreviveram e não sobreviveram na terceira classe é exatamente o mesmo, segundo a base analisada.

df %>%
  mutate(Survived = ifelse(Survived == 1, "Survived", "Died")) %>%
  group_by(Pclass, Sex, Survived) %>%
  summarise(count = n()) %>%
  mutate(Percentage = round(count/sum(count)*100,2)) %>%
  ggplot(aes(x = factor(Pclass), y = Percentage, fill = Survived)) +
  geom_col(position = "dodge") +
  geom_text(aes(label = count), position = position_dodge(width = 1), vjust = -0.5, color = "#202124", size = 3) +
  scale_fill_manual(name = "Sobreviveu?", values = c("#d3290f", "#52d053"), labels = c("Não", "Sim")) +
  scale_x_discrete(limits = c("1", "2", "3")) +
  facet_wrap(~Sex, nrow = 1, scales = "free_x") +
  labs(title = "Comparação de sobreviventes e óbitos por classe",
       subtitle = "Dados separados por sexo",
       x = "Classe",
       y = "Porcentagem (%)",
       fill = "") +
  theme(legend.position = "bottom",
        panel.grid.major.x = element_blank(),
        panel.grid.minor.x = element_blank())
`summarise()` has grouped output by 'Pclass', 'Sex'. You can override using the `.groups` argument.

Vizualização em Comparação a População

Relação do número de mortes pelo número total de passageiros por sexo.

  • Vemos como o número relativo de mortos da terceira classe é muito maior que comparado a outras classes em ambos os sexos.

  • Mesmo assim, o número relativo de sobreviventes homens na terceira classe é maior que da segunda classe.

# Agrupa os dados por classe de passageiros, gênero e sobrevivência
survival_by_class_gender <- df %>%
  group_by(Pclass, Survived, Sex) %>%
  summarise(count = n())
`summarise()` has grouped output by 'Pclass', 'Survived'. You can override using the `.groups` argument.
# Calcula a proporção e o percentual de sobreviventes em cada categoria
survival_by_class_gender$prop <- survival_by_class_gender$count / sum(survival_by_class_gender$count)
survival_by_class_gender$percent <- paste0(round(survival_by_class_gender$prop * 100, 1), "%")

# Cria um gráfico de barras empilhadas com as proporções de sobrevivência por classe e sobrevivência, 
# colorido de acordo com a variável de sobrevivência
ggplot(survival_by_class_gender, aes(x = factor(Pclass), y = prop, fill = factor(Survived))) +
  geom_bar(stat = "identity", position = "stack") + # indica que é um gráfico de barras empilhadas
  geom_text(aes(label = percent), position = position_stack(vjust = 0.5)) + 
  labs(title = "Proporção de sobrevivência ao Total", x = "Classe", y = "Proporção") + 
  theme(legend.position = "bottom") +
  scale_fill_manual(name = "Sobreviveu?", values = c("#d3290f", "#52d053"), labels = c("Não", "Sim")) + 
  facet_wrap(. ~ Sex) # adiciona um facet_wrap para separar os gráficos por gênero

Titanic Analytcis

@gabrielluizone

LS0tCnRpdGxlOiAiTyBJbmFmdW5kw6F2ZWwgcXVlIEFmdW5kb3UiCnN1YnRpdGxlOiAiVW1hIGFuw6FsaXNlIGRvcyBwYXNzYWdlaXJvcyBkbyBUaXRhbmljOiBzb2JyZXZpdsOqbmNpYSwgcGVyZmlsIGUgY29ycmVsYcOnw7VlcyIgCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmBgYApPIG5hdWZyw6FnaW8gZG8gVGl0YW5pYyDDqSB1bSBkb3MgZXZlbnRvcyBtYWlzIGNvbmhlY2lkb3MgZGEgaGlzdMOzcmlhIG1hcsOtdGltYS4gRW0gMTUgZGUgYWJyaWwgZGUgMTkxMiwgbyBuYXZpbyBxdWUgZXJhIGNvbnNpZGVyYWRvIGluYWZ1bmTDoXZlbCBjb2xpZGl1IGNvbSB1bSBpY2ViZXJnIGUgYWZ1bmRvdSwgcmVzdWx0YW5kbyBuYSBtb3J0ZSBkZSBtYWlzIGRlIDEuNTAwIHBlc3NvYXMuIEVzc2UgdHLDoWdpY28gYWNvbnRlY2ltZW50byBnZXJvdSBncmFuZGUgY29tb8Onw6NvIG5hIMOpcG9jYSBlLCBkZXNkZSBlbnTDo28sIHRlbSBzaWRvIG9iamV0byBkZSBpbsO6bWVyYXMgaW52ZXN0aWdhw6fDtWVzIGUgZXN0dWRvcy4gCgohW10oaHR0cHM6Ly9ici53ZWIuaW1nMi5hY3N0YS5uZXQvcl82NTRfMzY4L25ld3N2Ny8xNy8wNi8wMi8xNC8yNy8wOTEzNzkuanBnKQoKIyMjIEludHJvZHXDp8OjbwpDb20gYmFzZSBub3MgZGFkb3MgZG8gVGl0YW5pYywgYXByZXNlbnRhcmVtb3MgYSBzZWd1aXIgdW1hIGFuw6FsaXNlIHNvYnJlIG9zIHBhc3NhZ2Vpcm9zIGRvIG5hdmlvIHF1ZSBuYXVmcmFnb3UgZW0gMTkxMi4gU2Vyw6NvIGV4cGxvcmFkb3MgZGl2ZXJzb3MgYXNwZWN0b3MsIGNvbW8gYSBkaXN0cmlidWnDp8OjbyBkYXMgY2xhc3NlcyBzb2NpYWlzLCBhIHJlbGHDp8OjbyBlbnRyZSBnw6puZXJvIGUgc29icmV2aXbDqm5jaWEsIGEgaWRhZGUgZG9zIHBhc3NhZ2Vpcm9zLCBlbnRyZSBvdXRyb3MgZmF0b3JlcyByZWxldmFudGVzLgoKIyMjIE9iamV0aXZvCk8gb2JqZXRpdm8gZGEgYW7DoWxpc2Ugw6kgaW52ZXN0aWdhciBlIGNvbXByZWVuZGVyIG8gcGVyZmlsIGRvcyBwYXNzYWdlaXJvcyBlICoqZXhwbG9yYXIgYXMgY2FyYWN0ZXLDrXN0aWNhcyBxdWUgcG9kZW0gdGVyIGluZmx1ZW5jaWFkbyBhcyBjaGFuY2VzIGRlIHNvYnJldml2w6puY2lhIGRvcyBwYXNzYWdlaXJvcyoqLiBBIGZvbnRlIGRvcyBkYWRvcyB1dGlsaXphZG9zIHBvZGUgdmFyaWFyLCBtYXMgYWxndW1hcyBkYXMgbWFpcyBjb211bnMgc8OjbyBvcyByZWdpc3Ryb3Mgb2ZpY2lhaXMgZG9zIHBhc3NhZ2Vpcm9zIGRvIFRpdGFuaWMgZGlzcG9uw612ZWlzIHB1YmxpY2FtZW50ZSwgY29tbyBvcyBmb3JuZWNpZG9zIHBlbG8gc2l0ZSBLYWdnbGUgPGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vYy90aXRhbmljL2RhdGE+IGUgcGVsbyBNdXNldSBNYXLDrXRpbW8gTmFjaW9uYWwgZG9zIEVVQSA8aHR0cHM6Ly93d3cubWFyaXRpbWUub3JnL3RpdGFuaWMvcGFzc2VuZ2Vycy5odG0+LgoKIyMjIEJpYmxpb3RlY2FzCmBgYHtyfQojIENvbGXDp8OjbyBkZSBwYWNvdGVzIHBhcmEgbWFuaXB1bGHDp8OjbyBlIHZpc3VhbGl6YcOnw6NvIGRlIGRhZG9zCmlmKCFyZXF1aXJlKHRpZHl2ZXJzZSkpIGluc3RhbGwucGFja2FnZXMoJ3RpZHl2ZXJzZScpO2xpYnJhcnkodGlkeXZlcnNlKQoKIyBDcmnDp8OjbyBkZSBncsOhZmljb3MgZSB2aXN1YWxpemHDp8O1ZXMgZXN0YXTDrXN0aWNhcwppZighcmVxdWlyZShnZ3Bsb3QyKSkgaW5zdGFsbC5wYWNrYWdlcygnZ2dwbG90MicpO2xpYnJhcnkoZ2dwbG90MikKCiMgTWFuaXB1bGHDp8OjbyBkZSBkYWRvcywgY29tbyBmaWx0cmFnZW0sIHNlbGXDp8OjbyBlIGFncmVnYcOnw6NvCmlmKCFyZXF1aXJlKGRwbHlyKSkgaW5zdGFsbC5wYWNrYWdlcygnZHBseXInKTtsaWJyYXJ5KGRwbHlyKQoKIyBQbG90YXIgbWF0cml6ZXMgZGUgY29ycmVsYcOnw6NvIHVzYW5kbyBnZ3Bsb3QyCmlmKCFyZXF1aXJlKGdnY29ycnBsb3QpKSBpbnN0YWxsLnBhY2thZ2VzKCdnZ2NvcnJwbG90Jyk7bGlicmFyeShnZ2NvcnJwbG90KQppZighcmVxdWlyZShwbG90bHkpKSBpbnN0YWxsLnBhY2thZ2VzKCdwbG90bHknKTtsaWJyYXJ5KHBsb3RseSkKCiMgRnVuw6fDtWVzIHBhcmEgYWp1c3RhciBhIGVzY2FsYSBkb3MgZWl4b3MgZW0gZ3LDoWZpY29zIGdncGxvdDIKaWYoIXJlcXVpcmUoc2NhbGVzKSkgaW5zdGFsbC5wYWNrYWdlcygnc2NhbGVzJyk7bGlicmFyeShzY2FsZXMpCgojIEZvcm5lY2UgZnVuw6fDtWVzIHBhcmEgbWFuaXB1bGHDp8OjbyBkZSBzdHJpbmdzCmlmKCFyZXF1aXJlKHN0cmluZ3IpKSBpbnN0YWxsLnBhY2thZ2VzKCdzdHJpbmdyJyk7bGlicmFyeShzdHJpbmdyKQoKYGBgCgojIyMgSW1wb3J0YcOnw6NvIGRvcyBEYWRvcwoKYGBge3J9CmRmIDwtIHJlYWQuY3N2KCdkYXRhL3RpdGFuaWMuY3N2JykgIyBWYXJpw6F2ZWwgcHJpbmNpcGFsIGBTdXJ2aXZlZApoZWFkKGRmLCAzKQpgYGAKCnwgVmFyacOhdmVsIHwgRGVzY3Jpw6fDo28gfAp8IC0tLSB8IC0tLSB8CnwgUGFzc2VuZ2VySWQgfCBOw7ptZXJvIGRlIGlkZW50aWZpY2HDp8OjbyBkbyBwYXNzYWdlaXJvIHwKfCBTdXJ2aXZlZCB8IFBhc3NhZ2Vpcm8gc29icmV2aXZldSBhbyBuYXVmcsOhZ2lvPyAoMCA9IE7Do287IDEgPSBTaW0pIHwKfCBQY2xhc3MgfCBDbGFzc2Ugb25kZSBvIHBhc3NhZ2Vpcm8gZXN0YXZhIG5vIG5hdmlvICgxID0gMcKqIGNsYXNzZTsgMiA9IDLCqiBjbGFzc2U7IDMgPSAzwqogY2xhc3NlKSB8CnwgTmFtZSB8IE5vbWUgZG8gcGFzc2FnZWlybyB8CnwgU2V4IHwgU2V4byBiaW9sw7NnaWNvIHwKfCBBZ2UgfCBJZGFkZSB8CnwgU2liU3AgfCBOw7ptZXJvIGRlIGlybcOjb3Mgb3UgY8O0bmp1Z2VzIGEgYm9yZG8gfAp8IFBhcmNoIHwgTsO6bWVybyBkZSBwYWlzIG91IGZpbGhvcyBhIGJvcmRvIHwKfCBUaWNrZXQgfCBOw7ptZXJvIGRvIHRpY2tldCBkZSBlbWJhcnF1ZSAocGFzc2FnZW0pIHwKfCBGYXJlIHwgVmFsb3IgZGEgdGFyaWZhIChwcmXDp28gZGEgcGFzc2FnZW0pIGVtIExpYnJhcyBFc3RlcmxpbmFzIHwKfCBDYWJpbiB8IElkZW50aWZpY2HDp8OjbyBkYSBjYWJpbmUgfAp8IEVtYmFya2VkIHwgUG9ydG8gZGUgZW1iYXJxdWUgKEMgPSBDaGVyYm91cmc7IFEgPSBRdWVlbnN0b3duOyBTID0gU291dGhhbXB0b24pIHwKCiMjIEFuw6FsaXNlIGRhIFBvcHVsYWNpb25hbAoKIyMjIyMgVml6dWFsaXphw6fDo28gcGVsbyBTZXhvCgpgYGB7cn0KIyBDb250YXIgbsO6bWVybyBkZSBwYXNzYWdlaXJvcyBwb3Igc2V4bwpwYXNzZW5nZXJzX2J5X3NleCA8LSBkZiAlPiUKICBncm91cF9ieShTZXgpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkKCiMgQ2FsY3VsYXIgcHJvcG9yw6fDo28KcGFzc2VuZ2Vyc19ieV9zZXgkcHJvcCA8LSBwYXNzZW5nZXJzX2J5X3NleCRjb3VudCAvIHN1bShwYXNzZW5nZXJzX2J5X3NleCRjb3VudCkKCiMgQ3JpYXIgZ3LDoWZpY28gZGUgYmFycmFzIGVtcGlsaGFkYXMKZ2dwbG90KHBhc3NlbmdlcnNfYnlfc2V4LCBhZXMoeCA9IFNleCwgeSA9IHByb3AsIGZpbGwgPSBTZXgpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZShjb3VudCwgIigiLCBzY2FsZXM6OnBlcmNlbnQocHJvcCksICIpIikpLCAKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemU9NCkgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnVpw6fDo28gZGUgcGFzc2FnZWlyb3MgcG9yIHNleG8iLCB4ID0gIlNleG8iLCB5ID0gIlByb3BvcsOnw6NvIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM5OThlYzMiLCAiIzZkYThmNiIpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCgpgYGAKCiMjIyMjIFZpenVhbGl6YcOnw6NvIHBlbGEgU29icmV2aXZlbmNpYQoKYGBge3J9CmRmICU+JQogIGdyb3VwX2J5KFN1cnZpdmVkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIG11dGF0ZShwcm9wID0gY291bnQgLyBzdW0oY291bnQpLCAKICAgICAgICAgcGVyY2VudCA9IHBhc3RlMChyb3VuZChwcm9wICogMTAwLCAxKSwgIiUiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZmFjdG9yKFN1cnZpdmVkKSwgeSA9IGNvdW50LCBmaWxsID0gZmFjdG9yKFN1cnZpdmVkKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGdlb21fdGV4dChhZXMobGFiZWwgPSBwZXJjZW50KSwgCiAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpKSArCiAgbGFicyh0aXRsZSA9ICJRdWFudGlkYWRlIGRlIHNvYnJldml2ZW50ZXMgZSBtb3J0b3MiLAogICAgICAgeCA9ICJTb2JyZXZpdmV1PyIsCiAgICAgICB5ID0gIlF1YW50aWRhZGUiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJTb2JyZXZpdmV1PyIsCiAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gYygiI2QzMjkwZiIsICIjNTJkMDUzIiksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTsOjbyIsICJTaW0iKSkKYGBgCgojIyMgQ29ycmVsYcOnw7VlcyBlIERpcmXDp8O1ZXMKCmBgYHtyfQojIFNlbGVjaW9uYSBhcGVuYXMgYXMgdmFyacOhdmVpcyBudW3DqXJpY2FzIGUgcmVtb3ZlIGxpbmhhcyBjb20gdmFsb3JlcyBmYWx0YW50ZXMKIyBDcmlhciBvIGdyw6FmaWNvIGRlIGNvcnJlbGHDp8OjbwpkZiAlPiUKICBzZWxlY3RfaWYoaXMubnVtZXJpYykgJT4lICAjIHNlbGVjaW9uYSBhcGVuYXMgYXMgdmFyacOhdmVpcyBudW3DqXJpY2FzCiAgbmEub21pdCgpICU+JSAgIyByZW1vdmUgYXMgbGluaGFzIGNvbSB2YWxvcmVzIGZhbHRhbnRlcwogIGNvcigpICU+JSAgIyBjYWxjdWxhIGEgY29ycmVsYcOnw6NvIGVudHJlIGFzIHZhcmnDoXZlaXMKICBnZ2NvcnJwbG90KGxhYiA9IFRSVUUsIGxhYl9zaXplID0gMywgaGMub3JkZXIgPSBUUlVFLCB0eXBlID0gImxvd2VyIikgICMgY3JpYSBvIGdyw6FmaWNvCmBgYAoKIyMjIEFuw6FsaXNlIGRvcyBDb21wb25lbnRlcyBQcmluY2lwYWlzCgpgYGB7cn0KIyBDcmlhciB1bWEgdmFyacOhdmVsIGJpbsOhcmlhIHBhcmEgbyBnw6puZXJvIGUgcmVtb3ZlciBhcyBsaW5oYXMgY29tIHZhbG9yZXMgZmFsdGFudGVzCmRmX3BjYSA8LSBkZiAlPiUgCiAgbXV0YXRlKEdlbmVyZSA9IGlmZWxzZShTZXggPT0gJ2ZlbWFsZScsIDEsIDAgKSkgJT4lICAjIGNyaWEgdW1hIHZhcmnDoXZlbCBiaW7DoXJpYSBwYXJhIG8gZ8OqbmVybwogIHNlbGVjdChTdXJ2aXZlZCwgUGNsYXNzLCBHZW5lcmUsIEFnZSwgU2liU3AsIFBhcmNoLCBGYXJlKSAlPiUgICMgc2VsZWNpb25hIGFzIHZhcmnDoXZlaXMgbnVtw6lyaWNhcyByZWxldmFudGVzCiAgZHJvcF9uYSgpICAjIHJlbW92ZSBhcyBsaW5oYXMgY29tIHZhbG9yZXMgZmFsdGFudGVzCgojIE5vcm1hbGl6YSBvcyBkYWRvcyBlIGV4ZWN1dGEgbyBQQ0EKZGZfcGNhX25vcm0gPC0gYXBwbHkoZGZfcGNhLCAyLCBzY2FsZSkgIyBub3JtYWxpemEgb3MgZGFkb3MgZXhjbHVpbmRvIGEgcHJpbWVpcmEgY29sdW5hIChTdXJ2aXZlZCkKcGNhIDwtIHByY29tcChkZl9wY2Ffbm9ybSkgICMgcmVhbGl6YSBvIFBDQQoKIyBFeGliZSBpbmZvcm1hw6fDtWVzIHNvYnJlIGFzIGNvbXBvbmVudGVzIHByaW5jaXBhaXMKc3VtbWFyeShwY2EpCmBgYAoKIyMgVmlzdWFsaXphw6fDo28gZG9zIDNQQ0EgfCA3MSUgZG9zIERhZG9zCj4gQSB2aXN1YWxpemHDp8OjbyBncsOhZmljYSBkYXMgMyBwcmltZWlyYXMgY29tcG9uZW50ZXMgcHJpbmNpcGFpcyBtb3N0cm91IHF1ZSBob3V2ZSB1bWEgc2VwYXJhw6fDo28gZW50cmUgb3MgcGFzc2FnZWlyb3MgcXVlIHNvYnJldml2ZXJhbSBlIG9zIHF1ZSBuw6NvIHNvYnJldml2ZXJhbSwgc3VnZXJpbmRvIHF1ZSBlc3NhcyB2YXJpw6F2ZWlzIGZvcmFtIGltcG9ydGFudGVzCgpgYGB7cn0KIyBDcmlhIG8gZGF0YWZyYW1lIGNvbSBhcyB0csOqcyBwcmltZWlyYXMgY29tcG9uZW50ZXMgcHJpbmNpcGFpcyBlIGFkaWNpb25hIGEgdmFyacOhdmVsICdTdXJ2aXZlZCcKZGZfcGNhX3Bsb3RfM2QgPC0gYXMuZGF0YS5mcmFtZShwY2EkeFssIDE6M10pICAjIGV4dHJhaSBhcyB0csOqcyBwcmltZWlyYXMgY29tcG9uZW50ZXMgcHJpbmNpcGFpcwpkZl9wY2FfcGxvdF8zZCRTdXJ2aXZlZCA8LSBmYWN0b3IoZGZfcGNhJFN1cnZpdmVkLCBsZXZlbHMgPSBjKDAsIDEpLCBsYWJlbHMgPSBjKCJNb3JyZXUiLCAiVml2ZXUiKSkgICMKZGZfcGNhX3Bsb3RfM2QkUGNsYXNzIDwtIGZhY3RvcihkZl9wY2EkUGNsYXNzLCBsZXZlbHMgPSBjKDEsIDIsIDMpLCBsYWJlbHMgPSBjKCIzIiwgIjIiLCAiMSIpKQpkZl9wY2FfcGxvdF8zZCRHZW5lcmUgPC0gZmFjdG9yKGRmX3BjYSRHZW5lcmUsIGxldmVscyA9IGMoMCwgMSksIGxhYmVscyA9IGMoIkhvbWVtIiwgIk11bGhlciIpKQpkZl9wY2FfcGxvdF8zZCRTaWJTcCA8LSBmYWN0b3IoZGZfcGNhJFNpYlNwLCBsZXZlbHMgPSBjKDAsIDEsIDIsIDMsIDQsIDUsIDYpLCBsYWJlbHMgPSBjKCIwIiwgIjEiLCAiMiIsICIzIiwgIjQiLCAiNSIsICI2IikpCgojIENyaWEgbyBncsOhZmljbyBkZSBkaXNwZXJzw6NvIGRhcyBjb21wb25lbnRlcyBwcmluY2lwYWlzIGVtIDNECnBsb3RfbHkoZGZfcGNhX3Bsb3RfM2QsIHggPSB+UEMxLCB5ID0gflBDMiwgeiA9IH5QQzMsIGNvbG9yID0gfmZhY3RvcihTdXJ2aXZlZCksIHR5cGUgPSAic2NhdHRlcjNkIiwgbW9kZSA9ICJtYXJrZXJzIiwKICAgICAgICBjb2xvcnMgPSBjKCIjRUUyRTIxIiwgIiMxRDc4NzQiKSwgbWFya2VyID0gbGlzdChzaXplID0gNSkpICU+JQogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gIkNvbXBvbmVudGUgUHJpbmNpcGFsIDEiKSwKICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICJDb21wb25lbnRlIFByaW5jaXBhbCAyIiksCiAgICAgICAgICAgICAgICAgICAgICB6YXhpcyA9IGxpc3QodGl0bGUgPSAiQ29tcG9uZW50ZSBQcmluY2lwYWwgMyIpKSwKICAgICAgICAgbGVnZW5kID0gbGlzdCh0aXRsZSA9ICJTb2JyZXZpdmV1IiksIHRpdGxlID0gIkFuw6FsaXNlIGRlIENvbXBvbmVudGVzIFByaW5jaXBhaXMgZW0gM0QiKQpgYGAKCiMjIyBDb21wb25lbnRlcyBwZWxvIEdlbmVybwoKYGBge3J9CnBsb3RfbHkoZGZfcGNhX3Bsb3RfM2QsIHggPSB+UEMxLCB5ID0gflBDMiwgeiA9IH5QQzMsIGNvbG9yID0gfmZhY3RvcihHZW5lcmUpLCB0eXBlID0gInNjYXR0ZXIzZCIsIG1vZGUgPSAibWFya2VycyIsCiAgICAgICAgY29sb3JzID0gYygiIzM3ODRCOSIsICIjQjkzNzVFIiksIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDUpKSAlPiUKICBsYXlvdXQoc2NlbmUgPSBsaXN0KHhheGlzID0gbGlzdCh0aXRsZSA9ICJDb21wb25lbnRlIFByaW5jaXBhbCAxIiksCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQ29tcG9uZW50ZSBQcmluY2lwYWwgMiIpLAogICAgICAgICAgICAgICAgICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIkNvbXBvbmVudGUgUHJpbmNpcGFsIDMiKSksCiAgICAgICAgIGxlZ2VuZCA9IGxpc3QodGl0bGUgPSAiU2V4byIpLCB0aXRsZSA9ICJBbsOhbGlzZSBkZSBDb21wb25lbnRlcyBQcmluY2lwYWlzIHBlbG8gR8OqbmVybyIpCmBgYAojIyMgQ29tcG9uZW50ZXMgcGVsYSBDbGFzc2UKCmBgYHtyfQpwbG90X2x5KGRmX3BjYV9wbG90XzNkLCB4ID0gflBDMSwgeSA9IH5QQzIsIHogPSB+UEMzLCBjb2xvciA9IH5mYWN0b3IoUGNsYXNzKSwgdHlwZSA9ICJzY2F0dGVyM2QiLCBtb2RlID0gIm1hcmtlcnMiLAogICAgICAgIGNvbG9ycyA9IGMoIiNjZjJkYTQiLCAiIzJkY2YzZSIsICIjMmQ0OGNmIiksIG1hcmtlciA9IGxpc3Qoc2l6ZSA9IDUpKSAlPiUKICBsYXlvdXQoc2NlbmUgPSBsaXN0KHhheGlzID0gbGlzdCh0aXRsZSA9ICJDb21wb25lbnRlIFByaW5jaXBhbCAxIiksCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiQ29tcG9uZW50ZSBQcmluY2lwYWwgMiIpLAogICAgICAgICAgICAgICAgICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIkNvbXBvbmVudGUgUHJpbmNpcGFsIDMiKSksCiAgICAgICAgIGxlZ2VuZCA9IGxpc3QodGl0bGUgPSAiU29icmV2aXZldSIpLCB0aXRsZSA9ICJBbsOhbGlzZSBkZSBDb21wb25lbnRlcyBQcmluY2lwYWlzIGVtIDNEIikKYGBgCgoKIyMjIERpcmXDp8OjbyBkYXMgVmFyacOhdmVpcwo+ICoqVXRpbGlkYWRlOioqIEVudGVuZGVyIGNvbW8gYXMgdmFyacOhdmVpcyBzZSByZWxhY2lvbmFtIGVudHJlIHNpIGUgY29tIGFzIGNvbXBvbmVudGVzIHByaW5jaXBhaXMsIHBlcm1pdGluZG8gYSBpZGVudGlmaWNhw6fDo28gZGUgcGFkcsO1ZXMgZSB0ZW5kw6puY2lhcwoKYGBge3IsIGZpZy5oZWlnaHQ9NywgZmlnLndpZHRoPTd9CmJpcGxvdChwY2EsIHNjYWxlID0gMCwgY2V4ID0gMC42LCBjb2wgPSBjKCJ3aGl0ZSIsICIjMDA0NkZGIikpCmBgYAoKIyMjIFNvYnJldml2w6puY2lhIHBvciBHw6puZXJvCj4gQWdydXBhciBvcyBkYWRvcyBwb3IgZ8OqbmVybyBlIHNvYnJldml2w6puY2lhIGUgY2FsY3VsYXIgYXMgcG9yY2VudGFnZW5zIGRlIHNvYnJldml2w6puY2lhIHBvciBnw6puZXJvCgotIE1lc21vIGNvbSBvIG1haW9yIG7Dum1lcm8gZGUgaG9tZW5zIG5hIGVtYmFyY2HDp8Ojby4gTyBuw7ptZXJvIGRlIHNvYnJldml2ZW50ZXMgZG8gc2V4byBmZW1pbmlubyBmb2kgbWFpb3IgcXVlIGRvIHNleG8gbWFzY3VsaW5vLgoKLSBPIG7Dum1lcm8gZGUgbXVsaGVyZXMgc29icmV2aXZlbnRlcyBmb2kgY2VyY2EgZGUgM3ggbWFpb3IgcXVlIG8gbsO6bWVybyBkZSBob21lbnMgc29icmV2aXZlbnRlcy4KCgpgYGB7cn0KIyBhZ3J1cGFyIGRhZG9zIGUgY2FsY3VsYXIgcG9yY2VudGFnZW5zCnN1cnZpdmFsX2J5X2dlbmRlciA8LSBkZiAlPiUKICBncm91cF9ieShTZXgsIFN1cnZpdmVkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQogIG11dGF0ZShwZXJjZW50ID0gY291bnQgLyBzdW0oY291bnQpICogMTAwKQoKIyBwbG90YXIgZ3LDoWZpY28KZ2dwbG90KHN1cnZpdmFsX2J5X2dlbmRlciwgYWVzKHggPSBTZXgsIHkgPSBwZXJjZW50LCBmaWxsID0gZmFjdG9yKFN1cnZpdmVkKSkpICsKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNkMTUyNTIiLCAiIzUyZDA1MyIpLCBsYWJlbHMgPSBjKCJOw6NvIFNvYnJldml2ZXUiLCAiU29icmV2aXZldSIpKSArCiAgbGFicyh4ID0gIkfDqm5lcm8iLCB5ID0gIlBvcmNlbnRhZ2VtIiwgZmlsbCA9ICIiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYsIGZhY2UgPSAiYm9sZCIsIGhqdXN0ID0gMC41KSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnkgPSBlbGVtZW50X2xpbmUoY29sb3IgPSAiZ3JheTkwIiwgc2l6ZSA9IDAuNSksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGd1aWRlcyhmaWxsID0gZ3VpZGVfbGVnZW5kKHJldmVyc2UgPSBUUlVFLCBvdmVycmlkZS5hZXMgPSBsaXN0KHNpemU9NSkpKSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IHBhc3RlMChjb3VudCwgIiAoIiwgc3ByaW50ZigiJS4xZiIsIHBlcmNlbnQpLCAiJSkiKSwgeSA9IHBlcmNlbnQpLCAKICAgICAgICAgICAgcG9zaXRpb24gPSBwb3NpdGlvbl9zdGFjayh2anVzdCA9IDAuNSksIHNpemUgPSA0LCBjb2xvciA9ICIjMjAyMTI0IikKCmBgYAoKIyMjIERpc3RyaWJ1acOnw6NvIGRlIElkYWRlIGRvcyBQYXNzYWdlaXJvcyBkbyBUaXRhbmljCj4gQWdydXBhciBvcyBwYXNzYWdlaXJvcyBwb3IgZmFpeGEgZXTDoXJpYSBlIGFuYWxpc2FyIG8gbsO6bWVybyBkZSBwZXNzb2FzIHBvciBmYWl4YSBubyBiYXJjbwoKLSAgRGlzdHJpYnVpw6fDo28gZGUgaWRhZGUgZW0gdW1hIGVzY2FsYSBkZSAwIGEgODAgYW5vcy4gQWp1ZGEgYSBlbnRlbmRlciBtZWxob3IgY29tbyBhcyBpZGFkZXMgZXN0w6NvIGRpc3RyaWJ1w61kYXMgZW50cmUgb3MgcGFzc2FnZWlyb3MgZG8gbmF2aW8KCi0gIEEgbsO6bWVybyBkZSBwYXNzYWdlaXJvcyBlbnRyZSAyMCBlIDUwIGFub3Mgw6kgZG9taW5hbnRlIGNvbXBhcmFkbyBhcyBkZW1haXMgaWRhZGVzLiBBIG3DqWRpYSBkZSBpZGFkZSBlc3TDoSBwb3Igdm9sdGEgZGUgMzAgYW5vcy4KCmBgYHtyfQpnZ3Bsb3QoZGYsIGFlcyh4ID0gQWdlKSkgKwogIGdlb21faGlzdG9ncmFtKGJpbnMgPSAyMCwgYmlud2lkdGggPSAyLCBmaWxsID0gIiM1MzI4ZDQiLCBjb2xvciA9ICIjMjAyMTI0IikgKwogIGxhYnModGl0bGUgPSAiRGlzdHJpYnVpw6fDo28gZGUgSWRhZGUgZG9zIFBhc3NhZ2Vpcm9zIiwgeCA9ICJJZGFkZSIsIHkgPSAiRnJlcXXDqm5jaWEiKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGhqdXN0ID0gMC41KSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSwKICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEyKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgODAsIDEwKSkgKwogIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSBtZWFuKEFnZSwgbmEucm0gPSBUUlVFKSksIGNvbG9yID0gIiM4NmQ5NGUiLCBsaW5ldHlwZSA9ICJkYXNoZWQiLCBzaXplID0gMSkgKwogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IG1lYW4oZGYkQWdlLCBuYS5ybSA9IFRSVUUpLCB5ID0gbWF4KGRmJEFnZSkgKiAwLjksIGxhYmVsID0gIk3DqWRpYSBkYSBJZGFkZSIsIGNvbG9yID0gIiMyMDIxMjQiLCBzaXplID0gNSwgZm9udGZhY2UgPSAiYm9sZCIpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJMZWdlbmRhIikpCgpgYGAKCiMjIyMjIERlbnNpZGFkZQo+ICBBZ3J1cGFyIGFzIHBlc3NvYXMgcG9yIGlkYWRlIGUgYW5hbGlhc2FyIGEgZGVuc2lkYWRlIGRhIHNvYnJldml2w6puY2lhLgoKLSAgTsO6bWVybyByZWxhdGl2byBkZSBqb3ZlbnMgcXVlIHNvYnJldml2ZXJhbSBmb2kgbWFpb3IgcXVlIGFzIGRlbWFpcyBmYWl4YXMgZXTDoXJpYXMuCgotICBNZXNtbyBhc3NpbSwgbyBuw7ptZXJvIGRlIGpvdmVucyBtb3J0b3MgY2hlZ2EgYSBjZXJjYSBkZSA1MCUgZG8gdmFsb3IgdG90YWwgZGUgam92ZW5zIG5hIGVtYmFyY2HDp8Ojby4KCi0gIE7Dum1lcm8gZGUgbW9ydG9zIHBvciB2b2x0YSBkZSAyMyBhbm9zIMOpIG11aXRvIG1haW9yIHF1ZSBvIG7Dum1lcm8gZGUgc29icmV2aXZlbnRlcy4KCi0gIGNoYW5jZSBkZSBzb2JyZXZpdsOqbmNpYSBjYWkgYW8gcGFzc28gcXVlIGEgaWRhZGUgZG8gcGFzc2FnZWlybyBhdW1lbnRhLgoKYGBge3J9CiMgUmVtb3ZlciBvYnNlcnZhw6fDtWVzIGNvbSBpZGFkZSBmYWx0YW50ZQpkZl9hZ2UgPC0gZGZbIWlzLm5hKGRmJEFnZSksXQoKIyBHcsOhZmljbyBkZSBkZW5zaWRhZGUgcGFyYSBjYWRhIGdydXBvIGRlIHNvYnJldml2ZW50ZXMKZ2dwbG90KGRmX2FnZSwgYWVzKHggPSBBZ2UsIGZpbGwgPSBmYWN0b3IoU3Vydml2ZWQpKSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiRGVuc2lkYWRlIGRhIGlkYWRlIGRvcyBwYXNzYWdlaXJvcyBwb3Igc29icmV2aXbDqm5jaWEiLAogICAgICAgeCA9ICJJZGFkZSIsCiAgICAgICB5ID0gIkRlbnNpZGFkZSIpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gIlNvYnJldml2ZXU/IiwKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKCIjZDMyOTBmIiwgIiM1MmQwNTMiKSwKICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCJOw6NvIiwgIlNpbSIpKQpgYGAKCgojIyMgUmVsYWNpb25hbWVudG8gZW50cmUgU29icmV2aXbDqm5jaWEgZSBJZGFkZSBwb3IgU2V4bwo+IElkZW50aWZpY2FyIHNlIGjDoSBhbGd1bWEgcmVsYcOnw6NvIGVudHJlIGEgaWRhZGUgZG9zIHBhc3NhZ2Vpcm9zIGRvIFRpdGFuaWMgZSBzdWFzIGNoYW5jZXMgZGUgc29icmV2aXbDqm5jaWEsIGxldmFuZG8gZW0gY29uc2lkZXJhw6fDo28gbyBzZXhvIGRvcyBwYXNzYWdlaXJvcyAtCgotICBOb3ZhbWVudGUsIG9ic2VydmFtb3MgbyBtYWlvciBuw7ptZXJvIHJlbGF0aXZvIGRlIG1vcnRlcyBkZW50cmUgaG9tZW5zIGUsIHByaW5jaXBhbG1lbnRlLCBkZSAyMCBhIDUwIGFub3MuIAoKLSAgSMOhIHVtIGNhc28gcXVlIGF1bWVudGEgYSBjaGFuY2UgZGUgc29icmV2acOqbmNpYSBhY2ltYSBkZSA4MCBhbm9zIGRlbnRyZSBob21lbnMuCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTMuNX0KZGYgJT4lCiAgbmEub21pdCgpICU+JQogIG11dGF0ZShhZ2VfZ3JvdXAgPSBjdXQoQWdlLCBicmVha3MgPSBzZXEoMCwgbWF4KEFnZSkgKyA1LCBieSA9IDUpLCByaWdodCA9IEZBTFNFLCBsYWJlbHMgPSBwYXN0ZTAoc2VxKDAsIG1heChBZ2UpLCBieSA9IDUpLCAiLSIsIHNlcSg0LCBtYXgoQWdlKSwgYnkgPSA1KSkpKSAlPiUKICBjb3VudChhZ2VfZ3JvdXAsIFN1cnZpdmVkLCBTZXgpICU+JQogIG11dGF0ZShQZXJjZW50YWdlID0gcm91bmQobi9zdW0obikqMTAwLDIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBhZ2VfZ3JvdXAsIHkgPSBuLCBmaWxsID0gZmFjdG9yKFN1cnZpdmVkKSkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKFBlcmNlbnRhZ2UsICIlIikpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiIzIwMjEyNCIsIHNpemUgPSAzKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJTb2JyZXZpdmV1PyIsIHZhbHVlcyA9IGMoIiNkMzI5MGYiLCAiIzUyZDA1MyIpLCBsYWJlbHMgPSBjKCJOw6NvIiwgIlNpbSIpKSArCiAgZmFjZXRfd3JhcCh+IFNleCkgKwogIGxhYnModGl0bGUgPSAiRnJlcXXDqm5jaWEgZGUgU29icmV2aXZlbnRlcyBlIE1vcnRlcyBwb3IgSWRhZGUgZSBTZXhvIiwgeCA9ICJJZGFkZSIsIHkgPSAiRnJlcXXDqm5jaWEiKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpCmBgYAoKIyMjIFRheGEgZGUgU29icmV2aXZlbmNpYQo+IFJlbGHDp8OjbyBkbyBuw7ptZXJvIGRlIG1vcnRlcyBwZWxvIG7Dum1lcm8gdG90YWwgZGUgcGFzc2FnZWlyb3MgcG9yIGZhaXhhIGV0w6FyaWEuCgotICBBdW1lbnRvIGRhIHByb3BvcsOnw6NvIGRlIG1vcnRlcyBwb3IgZmFpeGEgZXTDoXJpYS4gRW50cmV0YW50bywgY29tbyBqw6Egb2JzZXJ2YWRvLCBmYWl4YSBkZSAxOSBhdMOpIDMwIGFub3MgcGVybWFuZWNlIGEgY29tIG1haW9yIGRlbnNpZGFkZSBkZSBtb3J0ZXMuICAKCi0gNTAlIGRvcyBqb3ZlbnMgY29tIDAgYSAxOCBhbm9zIG7Do28gc29icmV2aXZldQoKYGBge3J9CiMgQ3JpYW5kbyB1bSBkYXRhIGZyYW1lIGNvbSBhcyB2YXJpw6F2ZWlzIGRlIGludGVyZXNzZQpkZl9hZ2VfZmFyZSA8LSBkZiAlPiUKICBzZWxlY3QoQWdlLCBGYXJlLCBTdXJ2aXZlZCkgJT4lCiAgbmEub21pdCgpCgojIENyaWFuZG8gdmFyacOhdmVpcyBwYXJhIGNhdGVnb3JpemFyIGFzIGlkYWRlcwpkZl9hZ2VfZmFyZSRhZ2VfZ3JvdXAgPC0gY3V0KGRmX2FnZV9mYXJlJEFnZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygwLCAxOCwgMzAsIDUwLCBJbmYpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBjKCIwLTE4IiwgIjE5LTMwIiwgIjMxLTUwIiwgIjUxKyIpKQoKIyBDcmlhbmRvIHVtYSBub3ZhIHZhcmnDoXZlbCBwYXJhIGFybWF6ZW5hciBhcyBpbmZvcm1hw6fDtWVzIHNvYnJlIHNvYnJldml2w6puY2lhCmRmX2FnZV9mYXJlJHN1cnZpdmFsIDwtIGlmZWxzZShkZl9hZ2VfZmFyZSRTdXJ2aXZlZCA9PSAxLCAiU3Vydml2ZWQiLCAiRGllZCIpCgojIENhbGN1bGFuZG8gYSBwcm9wb3LDp8OjbyBkZSBzb2JyZXZpdmVudGVzIGUgbW9ydG9zIGVtIGNhZGEgZmFpeGEgZXTDoXJpYQpkZl9hZ2VfZmFyZV9zdW1tYXJ5IDwtIGRmX2FnZV9mYXJlICU+JQogIGdyb3VwX2J5KGFnZV9ncm91cCwgc3Vydml2YWwpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lCiAgbXV0YXRlKHByb3AgPSBjb3VudCAvIHN1bShjb3VudCkpCgojIENyaWFuZG8gdW0gZ3LDoWZpY28gZGUgYmFycmFzIGVtcGlsaGFkYXMgcGFyYSB2aXN1YWxpemFyIGEgcHJvcG9yw6fDo28gZGUgc29icmV2aXZlbnRlcyBlIG1vcnRvcyBlbSBjYWRhIGZhaXhhIGV0w6FyaWEKZ2dwbG90KGRmX2FnZV9mYXJlX3N1bW1hcnksIGFlcyh4ID0gYWdlX2dyb3VwLCB5ID0gcHJvcCwgZmlsbCA9IHN1cnZpdmFsKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgbGFicyh0aXRsZSA9ICJQcm9wb3LDp8OjbyBkZSBzb2JyZXZpdmVudGVzIGUgbW9ydG9zIHBvciBmYWl4YSBldMOhcmlhIiwKICAgICAgIHggPSAiRmFpeGEgZXTDoXJpYSIsCiAgICAgICB5ID0gIlByb3BvcsOnw6NvIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiU29icmV2aXbDqm5jaWEiLCAKICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBjKCJEaWVkIiA9ICIjZDMyOTBmIiwgIlN1cnZpdmVkIiA9ICIjNTJkMDUzIiksCiAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gYygiTW9ydG9zIiwgIlNvYnJldml2ZW50ZXMiKSkKYGBgCgoKIyMgUHJvYmFiaWxpZGFkZSBkZSBTb2JyZXZpdmVuY2lhIHBlbGEgQ2xhc3NlCj4gUmVsYcOnw6NvIGRvIG7Dum1lcm8gZGUgbW9ydGVzIHBlbG8gbsO6bWVybyB0b3RhbCBkZSBwYXNzYWdlaXJvcyBwb3IgY2xhc3NlIGRlIHBhc3NhZ2Vpcm9zLgoKLSAgRGVuc2lkYWRlIHJlbGF0aXZhIGUgbsO6bWVybyBicnV0byBkZSBtb3J0ZSBhbHTDrXNzaW1vIHBhcmEgYSAzwrAgY2xhc3NlLiAKCi0gTsO6bWVybyBkZSBwYXNzYWdlaXJvcyBhdW1lbnRhIGFvIGxvbmdvIGRhcyBjbGFzc2VzLCBhbyBwYXNzbyBxdWUgc3VhIGNoYW5jZSBkZSBzb2JyZXZpdsOqbmNpYSBkaW1pbnVpLgoKCmBgYHtyLCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD01fQpkZiAlPiUKICBncm91cF9ieShQY2xhc3MsIFN1cnZpdmVkKSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCksIC5ncm91cHMgPSAiZHJvcCIpICU+JQogIG11dGF0ZShQZXJjZW50YWdlID0gcm91bmQoY291bnQvc3VtKGNvdW50KSoxMDAsMikpICU+JQogIG11dGF0ZShTdXJ2aXZlZCA9IGlmZWxzZShTdXJ2aXZlZCA9PSAxLCAiU3Vydml2ZWQiLCAiRGllZCIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoUGNsYXNzKSwgeSA9IFBlcmNlbnRhZ2UsIGZpbGwgPSBTdXJ2aXZlZCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKGNvdW50KSksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSwgdmp1c3QgPSAtMC41LCBjb2xvciA9ICIjMjAyMTI0Iiwgc2l6ZSA9IDMpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGFzdGUwKHJvdW5kKFBlcmNlbnRhZ2UsIDApLCAiJSIpKSwgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDEpLCB2anVzdCA9IDEuNSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiU2l0dWHDp8OjbyIsIHZhbHVlcyA9IGMoIiNkMzI5MGYiLCAiIzUyZDA1MyIpLCBsYWJlbHMgPSBjKCJWYXNjbyIsICJWaXZldSIpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHM9YygiMSIsICIyIiwgIjMiKSkgKwogIGxhYnModGl0bGUgPSAiUXVhbnRpZGFkZSBkZSBzb2JyZXZpdmVudGVzIGUgw7NiaXRvcyBwb3IgY2xhc3NlIGRlIHBhc3NhZ2Vpcm9zIiwgeCA9ICJDbGFzc2UiLCB5ID0gIlByb3BvcsOnw6NvIikKCmBgYAoKIyMjIyMgQW7DoWxpc2UgbmFzIE1lc21hcyBQcm9wb3LDp8O1ZXMKPiBOw7ptZXJvIGJydXRvIGRlIHNvYnJldml2ZW50ZXMgZSBuw6NvIHNvYnJldml2ZW50ZXMgcG9yIGNsYXNzZSBlIHNleG8uCgotICBOb3ZhbWVudGUsIHBlcmNlYmUtc2UgYSBtYWlvciBwb3JjZW50YWdlbSBkZSBzb2JyZXZpdsOqbmNpYSBlbnRyZSBtdWxoZXJlcywgcHJpbmNpcGFsbWVudGUgZGUgY2xhc3NlcyBtYWlzIGFsdGFzLgoKLSAgSW50ZXJlc3NhbnRlIG8gZmF0byBkZSBxdWUgbyBuw7ptZXJvIGRlIG11bGhlcmVzIHF1ZSBzb2JyZXZpdmVyYW0gZSBuw6NvIHNvYnJldml2ZXJhbSBuYSB0ZXJjZWlyYSBjbGFzc2Ugw6kgZXhhdGFtZW50ZSBvIG1lc21vLCBzZWd1bmRvIGEgYmFzZSBhbmFsaXNhZGEuCgpgYGB7ciwgZmlnLndpZHRoPTksIGZpZy5oZWlnaHQ9NX0KZGYgJT4lCiAgbXV0YXRlKFN1cnZpdmVkID0gaWZlbHNlKFN1cnZpdmVkID09IDEsICJTdXJ2aXZlZCIsICJEaWVkIikpICU+JQogIGdyb3VwX2J5KFBjbGFzcywgU2V4LCBTdXJ2aXZlZCkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IHJvdW5kKGNvdW50L3N1bShjb3VudCkqMTAwLDIpKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBmYWN0b3IoUGNsYXNzKSwgeSA9IFBlcmNlbnRhZ2UsIGZpbGwgPSBTdXJ2aXZlZCkpICsKICBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gY291bnQpLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksIHZqdXN0ID0gLTAuNSwgY29sb3IgPSAiIzIwMjEyNCIsIHNpemUgPSAzKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJTb2JyZXZpdmV1PyIsIHZhbHVlcyA9IGMoIiNkMzI5MGYiLCAiIzUyZDA1MyIpLCBsYWJlbHMgPSBjKCJOw6NvIiwgIlNpbSIpKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShsaW1pdHMgPSBjKCIxIiwgIjIiLCAiMyIpKSArCiAgZmFjZXRfd3JhcCh+U2V4LCBucm93ID0gMSwgc2NhbGVzID0gImZyZWVfeCIpICsKICBsYWJzKHRpdGxlID0gIkNvbXBhcmHDp8OjbyBkZSBzb2JyZXZpdmVudGVzIGUgw7NiaXRvcyBwb3IgY2xhc3NlIiwKICAgICAgIHN1YnRpdGxlID0gIkRhZG9zIHNlcGFyYWRvcyBwb3Igc2V4byIsCiAgICAgICB4ID0gIkNsYXNzZSIsCiAgICAgICB5ID0gIlBvcmNlbnRhZ2VtICglKSIsCiAgICAgICBmaWxsID0gIiIpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICBwYW5lbC5ncmlkLm1ham9yLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vci54ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCiMjIyMjIFZpenVhbGl6YcOnw6NvIGVtIENvbXBhcmHDp8OjbyBhIFBvcHVsYcOnw6NvCj4gUmVsYcOnw6NvIGRvIG7Dum1lcm8gZGUgbW9ydGVzIHBlbG8gbsO6bWVybyB0b3RhbCBkZSBwYXNzYWdlaXJvcyBwb3Igc2V4by4KCi0gVmVtb3MgY29tbyBvIG7Dum1lcm8gcmVsYXRpdm8gZGUgbW9ydG9zIGRhIHRlcmNlaXJhIGNsYXNzZSDDqSBtdWl0byBtYWlvciBxdWUgY29tcGFyYWRvIGEgb3V0cmFzIGNsYXNzZXMgZW0gYW1ib3Mgb3Mgc2V4b3MuCgotICBNZXNtbyBhc3NpbSwgbyBuw7ptZXJvIHJlbGF0aXZvIGRlIHNvYnJldml2ZW50ZXMgaG9tZW5zIG5hIHRlcmNlaXJhIGNsYXNzZSDDqSBtYWlvciBxdWUgZGEgc2VndW5kYSBjbGFzc2UuIAoKYGBge3IsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTV9CiMgQWdydXBhIG9zIGRhZG9zIHBvciBjbGFzc2UgZGUgcGFzc2FnZWlyb3MsIGfDqm5lcm8gZSBzb2JyZXZpdsOqbmNpYQpzdXJ2aXZhbF9ieV9jbGFzc19nZW5kZXIgPC0gZGYgJT4lCiAgZ3JvdXBfYnkoUGNsYXNzLCBTdXJ2aXZlZCwgU2V4KSAlPiUKICBzdW1tYXJpc2UoY291bnQgPSBuKCkpCgojIENhbGN1bGEgYSBwcm9wb3LDp8OjbyBlIG8gcGVyY2VudHVhbCBkZSBzb2JyZXZpdmVudGVzIGVtIGNhZGEgY2F0ZWdvcmlhCnN1cnZpdmFsX2J5X2NsYXNzX2dlbmRlciRwcm9wIDwtIHN1cnZpdmFsX2J5X2NsYXNzX2dlbmRlciRjb3VudCAvIHN1bShzdXJ2aXZhbF9ieV9jbGFzc19nZW5kZXIkY291bnQpCnN1cnZpdmFsX2J5X2NsYXNzX2dlbmRlciRwZXJjZW50IDwtIHBhc3RlMChyb3VuZChzdXJ2aXZhbF9ieV9jbGFzc19nZW5kZXIkcHJvcCAqIDEwMCwgMSksICIlIikKCiMgQ3JpYSB1bSBncsOhZmljbyBkZSBiYXJyYXMgZW1waWxoYWRhcyBjb20gYXMgcHJvcG9yw6fDtWVzIGRlIHNvYnJldml2w6puY2lhIHBvciBjbGFzc2UgZSBzb2JyZXZpdsOqbmNpYSwgCiMgY29sb3JpZG8gZGUgYWNvcmRvIGNvbSBhIHZhcmnDoXZlbCBkZSBzb2JyZXZpdsOqbmNpYQpnZ3Bsb3Qoc3Vydml2YWxfYnlfY2xhc3NfZ2VuZGVyLCBhZXMoeCA9IGZhY3RvcihQY2xhc3MpLCB5ID0gcHJvcCwgZmlsbCA9IGZhY3RvcihTdXJ2aXZlZCkpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gInN0YWNrIikgKyAjIGluZGljYSBxdWUgw6kgdW0gZ3LDoWZpY28gZGUgYmFycmFzIGVtcGlsaGFkYXMKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcGVyY2VudCksIHBvc2l0aW9uID0gcG9zaXRpb25fc3RhY2sodmp1c3QgPSAwLjUpKSArIAogIGxhYnModGl0bGUgPSAiUHJvcG9yw6fDo28gZGUgc29icmV2aXbDqm5jaWEgYW8gVG90YWwiLCB4ID0gIkNsYXNzZSIsIHkgPSAiUHJvcG9yw6fDo28iKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKSArCiAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJTb2JyZXZpdmV1PyIsIHZhbHVlcyA9IGMoIiNkMzI5MGYiLCAiIzUyZDA1MyIpLCBsYWJlbHMgPSBjKCJOw6NvIiwgIlNpbSIpKSArIAogIGZhY2V0X3dyYXAoLiB+IFNleCkgIyBhZGljaW9uYSB1bSBmYWNldF93cmFwIHBhcmEgc2VwYXJhciBvcyBncsOhZmljb3MgcG9yIGfDqm5lcm8KCmBgYAojIyMgVGl0YW5pYyBBbmFseXRjaXMKW0BnYWJyaWVsbHVpem9uZV0oaHR0cHM6Ly93d3cubGlua2VkaW4uY29tL2luL2dhYnJpZWxsdWl6b25lLykK